<?php

namespace Biz\service\course;

use Biz\cache\course\OrderNoCache;
use Biz\model\course\CourseOrder as mCourseOrder;
use Biz\model\course\CourseOrderLog as mCourseOrderLog;
use Biz\module\Packages\Pay\IAP;
use Biz\module\Packages\Pay\Tiles as pTiles;
use Biz\module\Sys\ErrorConst;
use Biz\pockets\constInterface\PayConfig;
use Biz\service\course\Course as sCourse;
use Doraemon\pockets\constInterface\LinkConf;
use Doraemon\tools\HhzClient;
use Doraemon\tools\IdParse;
use Doraemon\tools\LinkFormat;
use Doraemon\tools\Log;

class CourseOrder
{

    public static function getOrderInfo($orderNo)
    {
        $info = mCourseOrder::getByWhere([
            'order_no' => $orderNo,
            'order_status' => mCourseOrder::STATUS_SUCCESS
        ]);
        return $info;
    }

    /**
     * 生成订单号
     * @param $courseId
     * @param $uid
     * @return string
     * @throws
     */
    public static function createOrderNo($courseId, $uid)
    {
        $orderNo = '';
        $orderList = mCourseOrder::selectByWhere([
            'course_id' => $courseId,
            'uid' => $uid,
            'order_status' => mCourseOrder::STATUS_SUCCESS
        ]);
        if ($orderList) {
            throw new \Exception('你已购买该课程');
        }
        if (OrderNoCache::dataLock($courseId . '-' . $uid, 1)) {
            $courseInfo = sCourse::getCourseInfo($courseId);
            if ($courseInfo) {
                $orderNo = self::genCourseOrderNo($courseId, $uid);
                $data = [
                    'course_id' => $courseId,
                    'title' => $courseInfo['title'],
                    'price' => $courseInfo['price'],
                    'original_price' => $courseInfo['original_price'],
                    'apple_gid' => $courseInfo['apple_gid'],
                ];
                OrderNoCache::setCache($orderNo, $uid, $data);//设置订单号课程缓存
            }
        } else {
            throw new \Exception('你操作太频繁了');
        }
        return $orderNo;

    }

    /**
     * 创建订单
     * @param $uid
     * @param $orderNo
     * @param $payWay
     * @param $orderInfo
     * @param $orderStatus
     * @return bool
     * @throws \Exception
     */
    public static function createOrder($uid, $orderNo, $payWay, $orderInfo, $orderStatus = mCourseOrder::STATUS_SUCCESS)
    {
        if (self::checkOrderNo($uid, $orderInfo['course_id'], $orderNo)) {
            $info = mCourseOrder::getByWhere(['order_no' => $orderNo]);
            $data = [
                'order_no' => $orderNo,
                'uid' => $orderInfo['uid'],
                'course_id' => $orderInfo['course_id'],
                'course_title' => $orderInfo['title'],
                'apple_gid' => $orderInfo['apple_gid'],
                'order_status' => $orderStatus,
                'buy_price' => $orderInfo['pay_amount'],
                'original_price' => $orderInfo['original_price'],
                'pay_way' => $payWay,
                'source' => self::getOrderSource($payWay)
            ];
            if (!$info) {
                mCourseOrder::insertData($data);
            } else {
                mCourseOrder::updateData($data, ['order_no' => $orderNo]);
            }
        } else {
            Log::debug('非法请求的订单号', $uid, $orderNo, $payWay, $orderInfo);
            throw new \Exception('非法请求的订单号');
        }
        self::addOrderLog($orderNo, $uid, mCourseOrderLog::LOG_TYPE_CREATE);
        return true;
    }

    private static function getOrderSource($payWay)
    {
        $source = HhzClient::getClientType();
        if ($source == '') {
            if (in_array($payWay, [PayConfig::_PAY_WAYS_IAP, PayConfig::_PAY_WAYS_TILES])) {
                $source = HhzClient::CLIENT_IOS;
            } else {
                $source = HhzClient::CLIENT_ANDROID;
            }
        }
        return $source;
    }

    /**
     * 生成课程订单号
     * @param $courseId
     * @param $uid
     * @return string
     */
    private static function genCourseOrderNo($courseId, $uid)
    {
        $microTime = bcmul(microtime(true), 10000);
        $microTime = sprintf('%s%s', date('His'), substr($microTime, -4, 3));
        $microTime = strtoupper(base_convert($microTime, 10, 32));
        $time = date('ymd');
        $parseId = strtoupper(base_convert($courseId, 10, 32));
        $hashUid = IdParse::hashUid($uid);
        $order = [
            $time,
            $microTime,
            $parseId,
            $hashUid
        ];
        $orderNo = implode('-', $order);
        $info = mCourseOrder::getByWhere(['order_no' => $orderNo]);
        if (!empty($info)) {
            self::genCourseOrderNo($courseId, $uid);
        }
        return $orderNo;
    }

    /**
     * 课程订单号获取uid
     * @param $orderNo
     * @return int|mixed
     */
    public static function getUidByOrderNo($orderNo)
    {
        $uid = 0;
        $arr = explode('-', $orderNo);
        if ($arr && count($arr) == 4) {
            $uid = $arr[3];
            $uid = IdParse::unHashUid($uid);
        }
        return $uid;
    }

    /**
     * 课程订单号获取courseId
     * @param $orderNo
     * @return int|mixed
     */
    public static function getCourseIdByOrderNo($orderNo)
    {
        $courseId = 0;
        $arr = explode('-', $orderNo);
        if ($arr && count($arr) == 4) {
            $courseId = $arr[2];
            $courseId = base_convert($courseId, 32, 10);
        }
        return $courseId;
    }

    /**
     * 检查用户订单号是否正确
     * @param $uid
     * @param $courseId
     * @param $orderNo
     * @return bool
     */
    public static function checkOrderNo($uid, $courseId, $orderNo)
    {
        $orderNoUid = self::getUidByOrderNo($orderNo);
        $orderCourseId = self::getCourseIdByOrderNo($orderNo);
        return ($uid == $orderNoUid && $courseId == $orderCourseId);
    }

    public static function getCashierAmount($orderNo)
    {
        $result = [];
        $courseId = self::getCourseIdByOrderNo($orderNo);
        $uid = self::getUidByOrderNo($orderNo);
        try {
            $courseInfo = sCourse::getCourseInfo($courseId);
            $cacheInfo = OrderNoCache::getCache($orderNo);
            if ($courseId != $cacheInfo['course_id'] || $courseInfo['price'] != $cacheInfo['price']) {
                throw new \Exception('商品价格已更改', ErrorConst::ERROR_PAY_ORDER_INFO_UNKNOW);
            }
            if ($courseInfo) {
                $result = [
                    'order_no' => $orderNo,
                    'uid' => $uid,
                    'course_id' => $courseId,
                    'title' => $courseInfo['title'],
                    'apple_gid' => $courseInfo['apple_gid'],
                    'original_price' => $courseInfo['original_price'],
                    'pay_amount' => $courseInfo['price'],
                    'paystop_time' => 0,
                    'buy_num' => 1,
                    'pay_ver' => 0,
                ];
            } else {
                throw new \Exception('商品不存在', ErrorConst::ERROR_PAY_ORDER_INFO_UNKNOW);
            }
        } catch (\Exception $e) {
            Log::warning('收银台订单支付信息异常', [
                'uid' => $uid,
                'course_id' => $courseId,
                'order_no' => $orderNo,
                'msg' => $e->getMessage()
            ]);
        }
        return $result;
    }

    /**
     * 支付成功回调
     * @param $orderNo
     * @param $payWay
     * @param $payNo
     * @param $payAmount
     * @param $payTime
     * @param int $payVer
     * @throws \Exception
     */
    public static function callbackPaySucc($orderNo, $payWay, $payNo, $payAmount, $payTime, $payVer = 0)
    {
        Log::info('course-order-pay-callback', [
            $orderNo,
            $payWay,
            $payNo,
            $payAmount,
            $payTime,
            $payVer
        ]);
        $info = mCourseOrder::getByWhere(['order_no' => $orderNo]);
        $courseId = self::getCourseIdByOrderNo($orderNo);
        if (!$info) {
            $orderInfo = OrderNoCache::getCache($orderNo);
            if (!$orderInfo) {
                $uid = self::getUidByOrderNo($orderNo);
                $courseInfo = sCourse::getCourseInfo($courseId);
                $orderInfo = [
                    'course_id' => $courseInfo['course_id'],
                    'uid' => $uid,
                    'title' => $courseInfo['title'],
                    'price' => $courseInfo['price'],
                    'original_price' => $courseInfo['original_price'],
                    'apple_gid' => $courseInfo['apple_gid'],
                ];
                if (bccomp($orderInfo['price'], $payAmount, 2) != 0) {
                    throw new \Exception('查询课程价格和订单价格不一致#payAmount:' . $payAmount . '#course_price:' . $orderInfo['price'] . '#course_id:' . $orderInfo['course_id']);
                }
            }
            if (bccomp($orderInfo['price'], $payAmount, 2) != 0) {
                throw new \Exception('课程价格和订单价格不正确#payAmount:' . $payAmount . '#course_price:' . $orderInfo['price'] . '#course_id:' . $orderInfo['course_id']);
            }
            $data = [
                'order_no' => $orderNo,
                'uid' => $orderInfo['uid'],
                'course_id' => $orderInfo['course_id'],
                'course_title' => $orderInfo['title'],
                'apple_gid' => $orderInfo['apple_gid'],
                'order_status' => mCourseOrder::STATUS_SUCCESS,
                'buy_price' => $orderInfo['price'],
                'original_price' => $orderInfo['original_price'],
                'pay_amount' => $payAmount,
                'pay_way' => $payWay,
                'pay_no' => $payNo,
                'pay_time' => $payTime,
                'pay_ver' => $payVer,
                'source' => self::getOrderSource($payWay)
            ];
            mCourseOrder::insertData($data);
        } else {
            $data = [
                'order_status' => mCourseOrder::STATUS_SUCCESS,
                'pay_amount' => $payAmount,
                'pay_way' => $payWay,
                'pay_no' => $payNo,
                'pay_time' => $payTime,
                'pay_ver' => $payVer
            ];
            mCourseOrder::updateData($data, ['order_no' => $orderNo]);
        }
        $uid = self::getUidByOrderNo($orderNo);
        $courseId = self::getCourseIdByOrderNo($orderNo);
        self::addOrderLog($orderNo, $uid, mCourseOrderLog::LOG_TYPE_PAY_SUCCESS);
        CourseOrder::sendSuccessMsg($uid, $courseId);
    }

    public static function addOrderLog($orderNo, $uid, $logType, array $data = [])
    {
        if (empty($uid)) {
            $uid = self::getUidByOrderNo($orderNo);
        }
        $courseId = self::getCourseIdByOrderNo($orderNo);
        $data = [
            'order_no' => $orderNo,
            'course_id' => $courseId,
            'uid' => $uid,
            'log_type' => $logType,
            'log_data' => $data ? json_encode($data, JSON_UNESCAPED_UNICODE) : ''
        ];
        mCourseOrderLog::insertData($data);
    }

    /**
     * 发下行消息
     * @param $uid
     * @param $courseId
     */
    public static function sendSuccessMsg($uid, $courseId)
    {
        $info = sCourse::getCourseInfo($courseId);
        if ($uid && $info) {
            // 下发通知
            $linkArr = LinkFormat::generateLink(LinkConf::LINK_APP_COURSE_DETAIL, json_encode(['id' => $courseId]));
            \Doraemon\cache\Queue::insertQueue('queue/Sysmsg/Send', [
                'msgCode' => 403,
                'to_uid' => $uid,
                'msgParams' => [
                    'teacher_nick' => $info['teacher_name'],
                    'course_title' => $info['title'],
                    'link' => isset($linkArr['app_template']) ? $linkArr['app_template'] : ''
                ],
            ], \Doraemon\cache\Queue::QUEUE_DORAEMON);
        }
    }

    public static function createOrderByIap($uid, $orderNo, $iapData)
    {
        $result = ['success' => 0];
        //获取订单信息
        $orderInfo = self::getCashierAmount($orderNo);
        if ($uid != $orderInfo['uid']) {
            throw new \Exception('订单信息与当前用户不匹配');
        }
        //判断用户是否已经购买
        $hasOrderInfo = mCourseOrder::getByWhere([
            'course_id' => $orderInfo['course_id'],
            'uid' => $uid,
            'order_status' => mCourseOrder::STATUS_SUCCESS
        ]);
        //已购买直接返回
        if ($hasOrderInfo) {
            return [
                'order_no' => $hasOrderInfo['order_no'],
                'success' => 1
            ];
        }
        if ($iapData && $iapData['receipt']['in_app']) {
            Log::info('创建iap付费课订单', [
                'order' => $orderInfo,
                'iapData' => $iapData
            ]);
            foreach ($iapData['receipt']['in_app'] as $transaction) {
                if ($orderInfo['apple_gid'] != $transaction['product_id']) {
                    continue;
                }
                Log::info('添加iap支付信息', [
                    'order_info' => $orderInfo,
                    'transation' => $transaction
                ]);
                IAP::createOrder([
                    'order_no' => $orderNo,
                    'pay_amount' => $orderInfo['pay_amount'],
                    'pay_ver' => IAP::_PAY_VER_DEFAULE,
                ], [
                    'order_type' => IAP::_PAY_ORDER_TYPE_COURSE,
                    'pay_no' => $transaction['transaction_id'],
                    'pay_time' => date('Y-m-d H:i:s', strtotime($transaction['purchase_date'])),
                    'callback_info' => $transaction
                ]);
                self::createOrder($uid, $orderNo, IAP::_PAY_WAYS_IAP, $orderInfo);
                CourseOrder::callbackPaySucc($orderInfo['order_no'], pTiles::_PAY_WAYS_IAP, $orderInfo['order_no'], $orderInfo['pay_amount'], date('Y-m-d H:i:s'));
                $result['order_no'] = $orderNo;
                $result['pay_amount'] = $orderInfo['pay_amount'];
                $result['success'] = 1;
                break;
            }
        }
        return $result;
    }



    /**
     * 生成免费订单号
     * @param $courseId
     * @param $uid
     * @return string
     * @throws
     */
    public static function createFreeOrderNo($courseId, $uid)
    {
        $orderNo = '';
        $courseInfo = sCourse::getCourseInfo($courseId);
        if ($courseInfo) {
            $orderNo = self::genCourseOrderNo($courseId, $uid);
            $data = [
                'course_id' => $courseId,
                'title' => $courseInfo['title'],
                'price' => $courseInfo['price'],
                'original_price' => $courseInfo['original_price'],
                'apple_gid' => $courseInfo['apple_gid'],
            ];
            OrderNoCache::setCache($orderNo, $uid, $data);//设置订单号课程缓存
        }
        return $orderNo;

    }
}